package sk.muf.mufpong;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.AudioManager;
import android.media.ToneGenerator;

public class Game {
    private final Paint paint = new Paint();
    private final int TIME_INTERVAL = 30;
    private final ToneGenerator toneGenerator = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
    private final int FIELD_WIDTH = 10800;
    private int myPosition = FIELD_WIDTH / 2;
    private int hisPosition = FIELD_WIDTH / 2;
    private final int FIELD_HEIGHT = 19200;
    private final int BALL_SIZE = 700;
    private final int PADDLE_HEIGHT = BALL_SIZE / 2;
    private final int PADDLE_WIDTH = BALL_SIZE * 2;
    private final int screenXCoef;
    private final int screenYCoef;
    private int ballX;
    private int ballY;
    private int angle;
    private int speed = 400;

    public Game(int screenWidth, int screenHeight) {
        screenXCoef = FIELD_WIDTH / screenWidth;
        screenYCoef = FIELD_HEIGHT / screenHeight;
        paint.setColor(Color.WHITE);
        resetGame();
    }

    private void resetGame() {
        angle = (int) (Math.random() * 180) + 90;
        ballX = myPosition;
        ballY = FIELD_HEIGHT - PADDLE_HEIGHT - BALL_SIZE / 2;
    }

    public void step() {
        //for sin = difx and cos = dify:
        //down 0deg
        //right 90deg
        //up 180deg
        //left 270deg
        ballX += Math.sin(Math.toRadians(angle)) * speed;
        ballY += Math.cos(Math.toRadians(angle)) * speed;
        checkCollision();
    }

    private void checkCollision() {
        //left bump
        if (ballX - BALL_SIZE / 2 < 0) {
            ballX = BALL_SIZE / 2;
            if (angle < 270) angle -= (angle - 180) * 2;
            else angle = 360 - angle;
            beep();
        }

        //right bump
        if (ballX + BALL_SIZE / 2 > FIELD_WIDTH) {
            ballX = FIELD_WIDTH - BALL_SIZE / 2;
            if (angle > 90) angle -= (angle - 180) * 2;
            else angle = 360 - angle;
            beep();
        }

        //up bump
        if (ballY - BALL_SIZE / 2 - PADDLE_HEIGHT < 0) {
            if (hisPosition - PADDLE_WIDTH / 2 < ballX + BALL_SIZE / 2
                    && hisPosition + PADDLE_WIDTH / 2 > ballX - BALL_SIZE / 2) {
                if (angle < 180) angle = 180 - angle;
                else angle = 540 - angle;
                ballY = BALL_SIZE / 2 + PADDLE_HEIGHT;
                beep();
            } else {
                resetGame();
            }
        }

        //down bump
        if (ballY + BALL_SIZE / 2 + PADDLE_HEIGHT > FIELD_HEIGHT) {
            if (myPosition - PADDLE_WIDTH / 2 < ballX + BALL_SIZE / 2
                    && myPosition + PADDLE_WIDTH / 2 > ballX - BALL_SIZE / 2) {
                if (angle < 180) angle = 180 - angle;
                else angle = 540 - angle;
                ballY = FIELD_HEIGHT - BALL_SIZE / 2 - PADDLE_HEIGHT;
                beep();
            } else {
                resetGame();
            }
        }
    }

    private void beep() {
        toneGenerator.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 100);
    }

    public void setMyPosition(int position) {
        myPosition = getFieldX(position);
        if (myPosition - PADDLE_WIDTH / 2 < 0) {
            myPosition = PADDLE_WIDTH / 2;
        }
        if (myPosition + PADDLE_WIDTH / 2 > FIELD_WIDTH) {
            myPosition = FIELD_WIDTH - PADDLE_WIDTH / 2;
        }
    }

    public void setHisPosition(int position) {
        hisPosition = getFieldX(position);
        if (hisPosition - PADDLE_WIDTH / 2 < 0) {
            hisPosition = PADDLE_WIDTH / 2;
        }
        if (hisPosition + PADDLE_WIDTH / 2 > FIELD_WIDTH) {
            hisPosition = FIELD_WIDTH - PADDLE_WIDTH / 2;
        }
    }

    public void drawMyself(Canvas canvas) {
        canvas.drawRect(
                getScreenX(myPosition - PADDLE_WIDTH / 2),
                getScreenY(FIELD_HEIGHT - PADDLE_HEIGHT),
                getScreenX(myPosition + PADDLE_WIDTH / 2),
                getScreenY(FIELD_HEIGHT),
                paint);

        canvas.drawRect(
                getScreenX(hisPosition - PADDLE_WIDTH / 2),
                getScreenY(0),
                getScreenX(hisPosition + PADDLE_WIDTH / 2),
                getScreenY(PADDLE_HEIGHT),
                paint);

        canvas.drawRect(
                getScreenX(ballX - BALL_SIZE / 2),
                getScreenY(ballY - BALL_SIZE / 2),
                getScreenX(ballX + BALL_SIZE / 2),
                getScreenY(ballY + BALL_SIZE / 2),
                paint);

        canvas.drawLine(
                getScreenX(0),
                getScreenY(FIELD_HEIGHT / 2),
                getScreenX(FIELD_WIDTH),
                getScreenY(FIELD_HEIGHT / 2),
                paint);
    }

    private int getScreenX(int fieldX) {
        return fieldX / screenXCoef;
    }

    private int getScreenY(int fieldY) {
        return fieldY / screenYCoef;
    }

    private int getFieldX(int screenX) {
        return screenX * screenXCoef;
    }

    public int getTimeInterval() {
        return TIME_INTERVAL;
    }
}
